package com.speily.utils;

import com.speily.zookeeperdemo.lock.MyConnectionStateListener;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @Auther: SPL
 * @Date: 2019-08-12 14:30
 * @Description: - 订单生成(使用zookeeper)
 */
@Slf4j
public class GenerateOrderImpl implements GenerateOrder{


    @Override
    public String getOrder() throws Exception {

        String clientName = Thread.currentThread().getName();
        final String path = "/lock_path";
        String orderCode;
        SimpleDateFormat fmt = new SimpleDateFormat("yyyyDDmm-HH:mm:ss|SSS");

        //创建zk客户端
        CuratorFramework zkClient = getClient();

        //服务监听
        MyConnectionStateListener connectionStateListener = new MyConnectionStateListener(path,"");
        zkClient.getConnectionStateListenable().addListener(connectionStateListener);

        //分布式锁
        final InterProcessMutex lock = new InterProcessMutex(zkClient, path);

        //使用acquire方法获取锁，等待time * unit时间获取锁，如果仍然没有获取锁，则直接返回false。
        if ( !lock.acquire(10, TimeUnit.SECONDS) ) {
            throw new IllegalStateException(clientName + " could not acquire the lock");
        }
        try {
            log.info(clientName + " has the lock");
            //生成订单号码，唯一无解，只能保证满足一定并发
            orderCode = fmt.format(new Date()) + new Random().nextLong();

        } finally {
            log.info(clientName + " releasing the lock");
            lock.release(); //总是在Final块中释放锁。如果该线程多次调用 了acquire()获取锁，则如果只调用 一次release()该锁仍然会被该线程持有。
        }
        return orderCode;
    }

    private static CuratorFramework getClient(){
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
        CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString("47.94.165.79:2181")
                .retryPolicy(retryPolicy)
                .sessionTimeoutMs(6000)
                .connectionTimeoutMs(3000)
                .namespace("order")
                .build();
        client.start();
        return client;
    }

}
